﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using CarbonExchange.Bll;

namespace CarbonExchange.Tests
{
    [TestClass]
    public class EmailActivationCodeTests : BaseTest
    {
        [TestMethod]
        public void EmailActivationCode_GetById_WithIncorrectId_ReturnsNull()
        {
            EmailActivationCodeFactory factory = new EmailActivationCodeFactory(_Context);
            Assert.IsNull(factory.GetById(int.MaxValue));
        }

        [TestMethod]
        public void EmailActivationCode_GetById_WithCorrectId_ReturnsNotNull()
        {
            EmailActivationCodeFactory factory = new EmailActivationCodeFactory(_Context);
            Assert.IsNotNull(factory.GetById(_TestEmailActivationCodes[0].Id));
        }

        [TestMethod]
        public void EmailActivationCode_GetById_WithCorrectId_PopulatesCorrectly()
        {
            EmailActivationCodeFactory factory = new EmailActivationCodeFactory(_Context);
            var tmp = factory.GetById(_TestEmailActivationCodes[1].Id);
            Assert.IsNotNull(tmp);
            Assert.AreEqual(_TestEmailActivationCodes[1].Id, tmp.Id);
            Assert.AreEqual(false, tmp.Activated);
            Assert.AreEqual("TestCode1", tmp.Code);
            Assert.AreEqual(DateTime.Parse("24/10/2008 12:00"), tmp.Created);
            Assert.AreEqual("testEmailActivated1@email.com", tmp.EmailAddress);
            Assert.AreEqual(_TestUsers[1].Id, tmp.UserId);
        }

        [TestMethod]
        public void EmailActivationCode_GetAllByUserId_WithIncorrectId_ReturnsEmptyCount()
        {
            EmailActivationCodeFactory factory = new EmailActivationCodeFactory(_Context);
            Assert.AreEqual(0, factory.GetAllByUserId(int.MaxValue).Count());
        }

        [TestMethod]
        public void EmailActivationCode_GetAllByUserId_WithCorrectId_ReturnsCorrectCount()
        {
            EmailActivationCodeFactory factory = new EmailActivationCodeFactory(_Context);
            Assert.AreEqual(2, factory.GetAllByUserId(_TestUsers[0].Id).Count());
        }

        [TestMethod]
        public void EmailActivationCode_GetAllByUserId_WithCorrectId_PopulatesCorrectly()
        {
            EmailActivationCodeFactory factory = new EmailActivationCodeFactory(_Context);
            var tmp = factory.GetAllByUserId(_TestUsers[0].Id).ToArray();
            Assert.IsNotNull(tmp);
            Assert.AreEqual(2, tmp.Count());
            Assert.AreEqual(_TestEmailActivationCodes[0].Id, tmp[0].Id);
            Assert.AreEqual(true, tmp[0].Activated);
            Assert.AreEqual("TestCode0", tmp[0].Code);
            Assert.AreEqual(DateTime.Parse("24/10/2008 12:00"), tmp[0].Created);
            Assert.AreEqual("testEmailActivated0@email.com", tmp[0].EmailAddress);
            Assert.AreEqual(_TestUsers[0].Id, tmp[0].UserId);
        }

        [TestMethod]
        public void EmailActivationCode_DeleteOne()
        {
            EmailActivationCodeFactory factory = new EmailActivationCodeFactory(_Context);
            var tmp = factory.GetById(_TestEmailActivationCodes[0].Id);
            factory.Delete(tmp);
            Assert.IsNull(factory.GetById(_TestEmailActivationCodes[0].Id));
            Assert.AreEqual(1, factory.GetAllByUserId(_TestUsers[0].Id).Count());
        }

        [TestMethod]
        public void EmailActivationCode_DeleteMany()
        {
            EmailActivationCodeFactory factory = new EmailActivationCodeFactory(_Context);
            var tmp = factory.GetAllByUserId(_TestUsers[0].Id);
            factory.Delete(tmp);
            Assert.IsNull(factory.GetById(_TestEmailActivationCodes[0].Id));
            Assert.AreEqual(0, factory.GetAllByUserId(_TestUsers[0].Id).Count());
        }


        [TestMethod]
        public void EmailActivationCode_UpdateOne()
        {
            EmailActivationCodeFactory factory = new EmailActivationCodeFactory(_Context);
            var id = _TestEmailActivationCodes[1].Id;
            var tmp = factory.GetById(id);

            Assert.IsNotNull(tmp);
            Assert.IsFalse(tmp.Activated);
            tmp.Activated = true;
            factory.Save(tmp);
            Assert.IsTrue(tmp.Activated);
            tmp = factory.GetById(id);
            Assert.IsTrue(tmp.Activated);
        }

        [TestMethod]
        public void EmailActivationCode_UpdateMany()
        {
            EmailActivationCodeFactory factory = new EmailActivationCodeFactory(_Context);
            int id = _TestUsers[0].Id;

            var tmp = factory.GetAllByUserId(id).ToArray();
            Assert.IsNotNull(tmp);
            Assert.AreEqual(2, tmp.Count());
            for (int i = 0; i < tmp.Count(); i++)
            {
                Assert.AreEqual(i % 2 == 0 ? true : false, tmp[i].Activated);
                tmp[i].Activated = i % 2 == 0 ? false : true;
            }
            factory.Save(tmp);
            for (int i = 0; i < tmp.Count(); i++)
            {
                Assert.AreEqual(i % 2 == 0 ? false : true, tmp[i].Activated);
            }
            tmp = factory.GetAllByUserId(id).ToArray();
            for (int i = 0; i < tmp.Count(); i++)
            {
                Assert.AreEqual(i % 2 == 0 ? false : true, tmp[i].Activated);
            }
        }

        [TestMethod]
        public void EmailActivationCode_InsertOne()
        {
            EmailActivationCodeFactory factory = new EmailActivationCodeFactory(_Context);
            var tmp = new EmailActivationCode(_TestUsers[0].Id, "activationTest@insert.com");
            var expectedDateTime = DateTime.Now;
            factory.Save(tmp);
            Assert.IsTrue(tmp.Id > 0);
            Assert.AreEqual(false, tmp.Activated);
            Assert.IsFalse(string.IsNullOrEmpty(tmp.Code));
            Assert.IsTrue(tmp.Created - expectedDateTime < TimeSpan.FromSeconds(1));
            Assert.AreEqual("activationTest@insert.com", tmp.EmailAddress);
            Assert.AreEqual(_TestUsers[0].Id, tmp.UserId);

            var tmp2 = factory.GetById(tmp.Id);
            Assert.AreEqual(tmp.Id, tmp2.Id);
            Assert.AreEqual(tmp.Activated, tmp2.Activated);
            Assert.AreEqual(tmp.Code, tmp2.Code);
            Assert.AreEqual(tmp.Created, tmp2.Created);
            Assert.AreEqual(tmp.EmailAddress, tmp2.EmailAddress);
            Assert.AreEqual(tmp.UserId, tmp2.UserId);

        }

        [TestMethod]
        public void EmailActivationCode_InsertMany()
        {
            EmailActivationCodeFactory factory = new EmailActivationCodeFactory(_Context);
            int noToTest = 3;
            int existingCount = factory.GetAllByUserId(_TestUsers[0].Id).Count();
            List<EmailActivationCode> tmp = new List<EmailActivationCode>();
            for(int i = 0; i < noToTest; i++)
            {
                tmp.Add(new EmailActivationCode(_TestUsers[0].Id, string.Format("activationTest{0}@insert.com", i)));
            }
            var expectedDateTime = DateTime.Now;
            factory.Save(tmp);
            
            for(int i = 0; i < noToTest; i++)
            {
                Assert.IsTrue(tmp[i].Id > 0);
                Assert.AreEqual(false, tmp[i].Activated);
                Assert.IsFalse(string.IsNullOrEmpty(tmp[i].Code));
                Assert.IsTrue(tmp[i].Created - expectedDateTime < TimeSpan.FromSeconds(1));
                Assert.AreEqual(string.Format("activationTest{0}@insert.com", i), tmp[i].EmailAddress);
                Assert.AreEqual(_TestUsers[0].Id, tmp[i].UserId);
            }

            var tmp2 = factory.GetAllByUserId(_TestUsers[0].Id).ToArray();
            Assert.AreEqual(noToTest + existingCount, tmp2.Count());
            for (int i = 0; i < noToTest; i++)
            {
                Assert.AreEqual(tmp[i].Id, tmp2[i + existingCount].Id);
                Assert.AreEqual(tmp[i].Activated, tmp2[i + existingCount].Activated);
                Assert.AreEqual(tmp[i].Code, tmp2[i + existingCount].Code);
                Assert.AreEqual(tmp[i].Created, tmp2[i + existingCount].Created);
                Assert.AreEqual(tmp[i].EmailAddress, tmp2[i + existingCount].EmailAddress);
                Assert.AreEqual(tmp[i].UserId, tmp2[i + existingCount].UserId);
            }
        }

        [TestMethod]
        [ExpectedException(typeof(Bll.Exceptions.ValidationException))]
        public void EmailActivationCode_ValidationWithIncorrectEmailAddressFails()
        {
            EmailActivationCodeFactory factory = new EmailActivationCodeFactory(_Context);
            EmailActivationCode tmp = new EmailActivationCode(_TestUsers[0].Id, "deny@mann.com");
            factory.Save(tmp);
        }

        [TestMethod]
        public void EmailActivationCode_ActivateEmailAddressWithIncorrectActivationCode_ReturnsCodeNotFound()
        {
            EmailActivationCodeFactory factory = new EmailActivationCodeFactory(_Context);
            UserFactory userFactory = new UserFactory(_Context);

            var tmp = userFactory.ActivateEmailAddress("Rubbish", "Password 1");
            Assert.AreEqual(Bll.UserFactory.ActivateEmailAddressResult.Results.CodeNotFound, tmp.Status);

            var tmpUser = userFactory.GetById(_TestEmailActivationCodes[1].UserId);
            Assert.IsFalse(tmpUser.EmailAuthenticated);
        }

        [TestMethod]
        public void EmailActivationCode_ActivateEmailAddressWithIncorrectPassword_ReturnsIncorrectPassword()
        {
            EmailActivationCodeFactory factory = new EmailActivationCodeFactory(_Context);
            UserFactory userFactory = new UserFactory(_Context);
            var tmp = userFactory.ActivateEmailAddress(_TestEmailActivationCodes[1].Code, "RubbishPassword 0");
            Assert.AreEqual(Bll.UserFactory.ActivateEmailAddressResult.Results.IncorrectPassword, tmp.Status);

            var tmpUser = userFactory.GetById(_TestEmailActivationCodes[1].UserId);
            Assert.IsFalse(tmpUser.EmailAuthenticated);
        }

        [TestMethod]
        public void EmailActivationCode_ActivateEmailAddressWithCorrectDetails_ReturnsSuccess()
        {
            EmailActivationCodeFactory factory = new EmailActivationCodeFactory(_Context);
            UserFactory userFactory = new UserFactory(_Context);
            
            var tmp = userFactory.ActivateEmailAddress(_TestEmailActivationCodes[1].Code, "Password1");
            Assert.AreEqual(Bll.UserFactory.ActivateEmailAddressResult.Results.Success, tmp.Status);

            var tmpUser = userFactory.GetById(_TestEmailActivationCodes[1].UserId);
            Assert.IsTrue(tmpUser.EmailAuthenticated);
            Assert.AreEqual("testEmailActivated1@email.com", tmpUser.EmailAddress);
        }

        [TestMethod]
        public void EmailActivationCode_GetByCode_WithValidCodeAndSiteId_ReturnsNotNull()
        {
            EmailActivationCodeFactory factory = new EmailActivationCodeFactory(_Context);
            Assert.IsNotNull(factory.GetByCode(_TestEmailActivationCodes[1].Code, _TestSite.Id));
        }

        [TestMethod]
        public void EmailActivationCode_GetByCode_WithInvalidCode_ReturnsNull()
        {
            EmailActivationCodeFactory factory = new EmailActivationCodeFactory(_Context);
            Assert.IsNull(factory.GetByCode("rubbish", _TestSite.Id));
        }

        [TestMethod]
        public void EmailActivationCode_GetByCode_WithInvalidSiteId_ReturnsNull()
        {
            EmailActivationCodeFactory factory = new EmailActivationCodeFactory(_Context);
            Assert.IsNull(factory.GetByCode(_TestEmailActivationCodes[1].Code, _AlternateSite.Id));
        }
    }
}
